package startup.security.config;

import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;

/**
 * @author ly
 * @date : 2023/02/23 14:54
 */
@Slf4j
public class AmazonS3Manager {

    private static String AMAZON_ENDPOINT_URL;
    private static String AMAZON_AWS_ACCESS_KEY;
    private static String AMAZON_AWS_SECRET_KEY;


    static {

        try {

            AMAZON_ENDPOINT_URL = "https://epc-dev.s3.cn-north-1.amazonaws.com.cn/";
            AMAZON_AWS_ACCESS_KEY = "AKIATBYC5AJG5LCBXX6A";
            AMAZON_AWS_SECRET_KEY = "Qj4471I7F/bzPcmQJVLJoya/u8jHBgrq2LB8MZrh4B7fH68Xcm";
        } catch (Exception e) {
            log.error("amazonS3文件服务器基础参数加载出错" + e.getMessage());
        }
        log.info("amazonS3 文件服务器基础参数加载完成 access_key=" + AMAZON_AWS_ACCESS_KEY + " endpoint_url=" + AMAZON_ENDPOINT_URL);
    }


    /**
     * 初始化连接，每次使用需要重新连接
     */
    public static AmazonS3 initAmazonS3() {

        AmazonS3 s3 = new AmazonS3Client(new BasicAWSCredentials(AMAZON_AWS_ACCESS_KEY, AMAZON_AWS_SECRET_KEY));
        s3.setRegion(Region.getRegion(Regions.CN_NORTH_1));
        s3.setEndpoint(AMAZON_ENDPOINT_URL);
        s3.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
        return s3;
    }

    /**
     * 上传文件
     *
     * @param bucketName     桶名
     * @param tempFile       待上传文件
     * @param remoteFileName 文件名
     * @return
     */
    public static boolean uploadToS3(String bucketName, File tempFile, String remoteFileName, CannedAccessControlList fileType) {

        try {
            AmazonS3 s3 = initAmazonS3();

            if (!s3.doesBucketExistV2(bucketName)) {
                s3.createBucket(bucketName);
            }
            s3.putObject(new PutObjectRequest(bucketName, remoteFileName, tempFile).withCannedAcl(fileType));
            return true;
        } catch (Exception ase) {
            log.error("amazonS3上传文件File模式异常 " + ase.getMessage(), ase);
        }
        return false;
    }

    /**
     * 上传文件
     *
     * @param bucketName     桶名
     * @param multipartFile  待上传文件
     * @param remoteFileName 文件名
     * @return
     */
    public static boolean uploadToS3(String bucketName, CommonsMultipartFile multipartFile, String remoteFileName, CannedAccessControlList fileType) {

        InputStream in = null;
        try {
            AmazonS3 s3 = initAmazonS3();
            in = multipartFile.getInputStream();
            FileItem fileItem = multipartFile.getFileItem();

            if (!s3.doesBucketExistV2(bucketName)) {
                s3.createBucket(bucketName);
            }
            ObjectMetadata omd = new ObjectMetadata();
            omd.setContentType(fileItem.getContentType());
            omd.setContentLength(fileItem.getSize());
            omd.setHeader("filename", fileItem.getName());

            s3.putObject(new PutObjectRequest(bucketName, remoteFileName, in, omd).withCannedAcl(fileType));
            return true;

        } catch (Exception ase) {
            log.error("amazonS3上传文件InputStream模式异常 " + ase.getMessage(), ase);

        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error("amazonS3上传文件 关闭InputStream流异常 " + e.getMessage(), e);
                }
            }
        }
        return false;
    }


    /**
     * 下载文件
     *
     * @param bucketName     桶名
     * @param remoteFileName 文件名
     * @param path           下载路径
     */
    public static boolean downFromS3(String bucketName, String remoteFileName, String path) {
        try {
            AmazonS3 s3 = initAmazonS3();

            GetObjectRequest request = new GetObjectRequest(bucketName, remoteFileName);
            ObjectMetadata metadata = s3.getObject(request, new File(path));
            return true;
        } catch (Exception ase) {
            log.error("amazonS3下载文件异常 " + ase.getMessage(), ase);
        }
        return false;
    }


    /**
     * 删除文件
     *
     * @param bucketName     桶名
     * @param remoteFileName 待删除文件名
     * @throws IOException
     */
    public static void delFromS3(String bucketName, String remoteFileName) {
        try {
            AmazonS3 s3 = initAmazonS3();
            s3.deleteObject(bucketName, remoteFileName);
        } catch (Exception ase) {
            log.error("amazonS3删除文件异常 " + ase.getMessage(), ase);
        }
    }


    /**
     * 获取短链接 带过期时间
     *
     * @param bucketName     桶名称
     * @param remoteFileName 文件名称
     * @param expiration     过期时间/秒
     */
    public static String getUrlFromS3(String bucketName, String remoteFileName, int expiration) {
        try {
            AmazonS3 s3 = initAmazonS3();
            GeneratePresignedUrlRequest httpRequest = new GeneratePresignedUrlRequest(bucketName, remoteFileName);
            httpRequest.setExpiration(new Date(System.currentTimeMillis() + expiration * 1000));

            URL url = s3.generatePresignedUrl(httpRequest);
            return String.valueOf(url);
        } catch (Exception e) {
            log.error("amazonS3获取临时链接异常 " + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取永久链接
     *
     * @param bucketName     桶名称
     * @param remoteFileName 文件名称
     */
    public static String getUrlFromS3(String bucketName, String remoteFileName) {

        String url = "";
        try {
            AmazonS3 s3 = initAmazonS3();
            GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucketName, remoteFileName);
            url = String.valueOf(s3.generatePresignedUrl(urlRequest)).split("\\?")[0];
            if (url.indexOf(remoteFileName) == -1) {
                throw new RuntimeException("url文件名称校验不合法");
            }
            return url;

        } catch (Exception e) {
            log.error("amazonS3获取永久链接异常 " + e.getMessage(), e);
            return "";
        }
    }

    /**
     * 获取永久链接-包含证书
     *
     * @param bucketName     桶名称
     * @param remoteFileName 文件名称
     */
    public static String getUrlToS3(String bucketName, String remoteFileName) {
        try {
            AmazonS3 s3 = initAmazonS3();
            GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucketName, remoteFileName);
            URL url = s3.generatePresignedUrl(urlRequest);
            return String.valueOf(url);

        } catch (Exception e) {
            log.error("amazonS3获取永久链接异常 " + e.getMessage(), e);
            return null;
        }
    }

    public static AmazonS3 getS3() {
        return initAmazonS3();
    }

    /**
     * 根据桶名称获取文件集合
     */
    public static List<S3ObjectSummary> getFileMsgByBucketName(String bucketName) {
        AmazonS3 s3 = initAmazonS3();
        ObjectListing objectListing = s3.listObjects(bucketName);
        List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
        return objectSummaries;
    }
}
